package com.itic.appbase.framework.common.controller;

import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itic.appbase.framework.common.basevo.User;
import com.itic.appbase.framework.common.constants.IticConst;
import com.itic.appbase.framework.common.persistence.model.BaseExample;
import com.itic.appbase.framework.exception.definition.SessionTimeoutException;
import com.itic.appbase.framework.plugins.json.IticJsonMapper;
import com.itic.appbase.framework.plugins.logger.Log;
import com.itic.appbase.framework.plugins.mybatis.Page;
import com.itic.appbase.framework.utils.DateHelper;
import com.itic.appbase.framework.utils.NumberStringHelper;
import com.itic.appbase.framework.utils.StringHelper;
import com.itic.appbase.framework.utils.configuration.PropertyHelper;

/**
 * 基础Controller，所有controller都需要继承. 常用方法：<br>
 * 1.获取登录用户 findUserSession<br>
 * 2.获取登录用户ID, findUserId<br>
 * 3.获取前台参数并trim, getCleanParams<br>
 * 4.处理分页参数，handlePageQuery<br>
 * <p>
 * Company: itic
 * </p>
 * 
 * @author: idong
 * @date: 2015年5月8日 上午11:16:33
 * @version: V1.0
 */
public class BaseController {
    @Autowired
    protected IticJsonMapper iticJsonMapper;
    protected Logger LOGGER = Log.get(getClass());
    /**
     * 调用responser.writer，返回JSON格式数据.
     * 
     * @param response
     *            绑定的response
     * @param jsonObject
     *            需要转换的数据
     * @throws JsonProcessingException
     * @throws Exception
     */
    protected void responseJson(HttpServletResponse response, Object jsonObject)
            throws IOException {
        response.setContentType("application/json; charset=UTF-8");
        response.setHeader("Cache-Control", "no-cache");
        response.setCharacterEncoding("UTF-8");
        Object result = jsonObject;
        if (jsonObject instanceof String) {
            Map<String, Object> resultMap = new HashMap<String, Object>();
            resultMap.put("result", jsonObject);
            result = resultMap;
        }
        ObjectMapper mapper = new ObjectMapper();
        String jsonStr = mapper.writeValueAsString(result);
        response.getWriter().write(jsonStr);
        response.getWriter().flush();
    }

    /**
     * 调用responser.writer，返回TEXT格式数据.
     * 
     * @param response
     * @param text
     * @throws IOException
     * @throws
     */
    protected void responseText(HttpServletResponse response, String text)
            throws IOException {
        response.setContentType("text/plain; charset=UTF-8");
        response.setHeader("Cache-Control", "no-cache");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(text);
        response.getWriter().flush();
    }

    /**
     * 获取请求的对应IP地址.
     * 
     * @param request
     * @return
     * @throws
     */
    protected String toIpAddr(HttpServletRequest request) {
        List<String> checkList = new ArrayList<String>();
        checkList.add("X-Forwarded-For");
        checkList.add("Proxy-Client-IP");
        checkList.add("WL-Proxy-Client-IP");
        checkList.add("HTTP_CLIENT_IP");
        checkList.add("HTTP_X_FORWARDED_FOR");
        String ip = "";
        for (String header : checkList) {
            ip = request.getHeader(header);
            if (StringHelper.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
                break;
            }
        }
        if (StringHelper.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        return ip;
    }

    /**
     * 获取session中保存的USER对象.
     * 
     * @param request
     * @return
     * @throws
     */
    protected User findUserSession(HttpServletRequest request) {
        Object obj = request.getSession().getAttribute(IticConst.PS_SESSION_USERINFO_KEY);
        if (obj instanceof User) {
            return (User) obj;
        } else {
            throw new SessionTimeoutException();
        }
    }

    /**
     * 设置session中的USER对象.
     * 
     * @param request
     * @param user
     * @throws
     */
    protected void setUserSession(HttpServletRequest request, User user) {
        request.getSession().setAttribute(IticConst.PS_SESSION_USERINFO_KEY, user);
    }

    /**
     * 清除session中的USER对象.
     * 
     * @param request
     * @throws
     */
    protected void cleanUserSession(HttpServletRequest request) {
        request.getSession().removeAttribute(IticConst.PS_SESSION_USERINFO_KEY);
    }

    /**
     * 获取session中USER对象的ID.
     * 
     * @param request
     * @return
     * @throws
     */
    protected String findUserId(HttpServletRequest request) {
        Object obj = request.getSession().getAttribute(IticConst.PS_SESSION_USERINFO_KEY);
        if (obj instanceof User) {
            return ((User) obj).getUserId();
        }
        return "";
    }

    /**
     * 获取request中的指定参数，并进行trim处理.
     * 
     * @param request
     * @param paramName
     * @return
     * @throws
     */
    protected String getCleanParams(HttpServletRequest request, String paramName) {
        String result = null;
        String param = request.getParameter(paramName);
        result = StringHelper.getCleanString(param);
        return result;
    }

    /**
     * 处理请求中的P分页参数并设置给example.
     * 
     * @param request
     * @return
     * @throws Exception
     *             getCleanParams
     * @throws Exception
     *             parseInt
     */
    protected <T extends BaseExample> T handlePageQuery(HttpServletRequest request, T example) {
        Page page = null;
        String recordNow = this.getCleanParams(request, IticConst.RECORD_NOW);
        String pageSize = this.getCleanParams(request, IticConst.PAGE_SIZE);
        if (StringHelper.isNotEmpty(recordNow) && StringHelper.isNotEmpty(pageSize)) {
            page = new Page();
            page.setRecordNow(Integer.parseInt(recordNow));
            page.setPageSize(Integer.parseInt(pageSize));
        }
        example.setPage(page);
        return example;
    }
    
    /**
     * 处理请求中的P分页参数并设置给example.
     * 
     * @param request
     * @return
     * @throws Exception
     *             getCleanParams
     * @throws Exception
     *             parseInt
     */
    protected <T extends BaseExample> T handlePageQueryForMysql(HttpServletRequest request, T example) {
        Page page = null;
        String recordNow = this.getCleanParams(request, IticConst.RECORD_NOW);
        String pageSize = this.getCleanParams(request, IticConst.PAGE_SIZE);
        if (StringHelper.isNotEmpty(recordNow) && StringHelper.isNotEmpty(pageSize)) {
            page = new Page();
            //如果数据库是mysql的话
            if( "mysql".equals(PropertyHelper.getString("app.db.type")) ){
            	recordNow=NumberStringHelper.mulString(recordNow, pageSize);
            }
            page.setRecordNow(Integer.parseInt(recordNow));
            page.setPageSize(Integer.parseInt(pageSize));
        }else{
        	page = new Page();
            page.setRecordNow(0);
            page.setPageSize(10);
        }
        example.setPage(page);
        return example;
    }
    
    /**
     * 处理请求中的P分页参数并设置给example.
     * 
     * @param request
     * @return
     * @throws Exception
     *             getCleanParams
     * @throws Exception
     *             parseInt
     */
    protected <T extends BaseExample> T handlePageQueryDefault(HttpServletRequest request, T example) {
        Page page = null;
        String recordNow = this.getCleanParams(request, IticConst.RECORD_NOW);
        String pageSize = this.getCleanParams(request, IticConst.PAGE_SIZE);
        if (StringHelper.isNotEmpty(recordNow) && StringHelper.isNotEmpty(pageSize)) {
            page = new Page();
            //如果数据库是mysql的话
            if( "mysql".equals(PropertyHelper.getString("app.db.type")) ){
            	recordNow=NumberStringHelper.mulString(recordNow, pageSize);
            }
            page.setRecordNow(Integer.parseInt(recordNow));
            page.setPageSize(Integer.parseInt(pageSize));
        }else{
        	page = new Page();
            page.setRecordNow(0);
            page.setPageSize(10);
        }
        example.setPage(page);
        return example;
    }
    
    /**
     * 处理请求中的P分页参数并设置给example.
     * 
     * @param request
     * @return
     * @throws Exception
     *             getCleanParams
     * @throws Exception
     *             parseInt
     */
    protected <T extends BaseExample> T handlePageQuery(T example,String length ) {
        Page page = null;
        String recordNow = "0";
        String pageSize = length;
        if (StringHelper.isNotEmpty(recordNow) && StringHelper.isNotEmpty(pageSize)) {
            page = new Page();
            page.setRecordNow(Integer.parseInt(recordNow));
            page.setPageSize(Integer.parseInt(pageSize));
        }
        example.setPage(page);
        return example;
    }
    
    
    /**
     * 格式化查询区域开始时间
     * @param startTime
     * @return
     */
    protected Date fixStartTime(String startTime) {
        return DateHelper.parseDate(startTime + IticConst.START_TIME_SUFFIX);
    }
    
    /**
     * 格式化查询区域结束时间
     * @param startTime
     * @return
     */
    protected Date fixEndTime(String endTime) {
        return DateHelper.parseDate(endTime + IticConst.END_TIME_SUFFIX);
    }

    /**
     * 数据binder.
     * 
     * @param binder
     * @throws
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        // String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
            }

            @Override
            public String getAsText() {
                Object value = getValue();
                return value != null ? value.toString() : "";
            }
        });
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                if (StringHelper.isNotBlank(text)){
                    setValue(DateHelper.parseDate(text));
                }
            }
        });
        binder.registerCustomEditor(Double.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                if (StringHelper.isNotBlank(text)){
                    setValue(Double.parseDouble(text));
                }
            }
        });
        binder.registerCustomEditor(Long.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                if (StringHelper.isNotBlank(text)){
                    setValue(Long.parseLong(text));
                }
            }
        });
        binder.registerCustomEditor(Short.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                if (StringHelper.isNotBlank(text)){
                    setValue(Short.parseShort(text));
                }
            }
        });
        binder.registerCustomEditor(Boolean.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                if (StringHelper.isNotBlank(text)){
                    setValue(Boolean.parseBoolean(text));
                }
            }
        });
        binder.registerCustomEditor(Float.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                if (StringHelper.isNotBlank(text)){
                    setValue(Float.parseFloat(text));
                }
            }
        });
        binder.registerCustomEditor(Integer.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                if (StringHelper.isNotBlank(text)){
                    setValue(Integer.parseInt(text));
                }
            }
        });
    }
}
